package org.ytor.core.sysapi.monitor.api;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.ytor.common.model.R;
import org.ytor.core.sysapi.monitor.logic.SystemMonitorLogic;
import org.ytor.core.sysapi.monitor.resp.*;

import java.util.List;
import java.util.Map;

/**
 * created by yangtong on 2025/7/6 21:25:59
 * <br/>
 */
@Slf4j
@Tag(name = "系统监控", description = "系统监控相关接口")
@RestController
@RequestMapping("/sys/monitor")
@RequiredArgsConstructor
public class SysMonitorController {

    private final SystemMonitorLogic systemMonitorLogic;

    /**
     * 获取操作系统基础信息
     */
    @GetMapping("/operateSystemBasic")
    @Operation(summary = "操作系统信息", description = "获取操作系统基本信息")
    public R<OperateSystemBasicResp> operateSystemBasic() {
        try {
            return R.success(systemMonitorLogic.operateSystemBasic());
        } catch (Exception e) {
            log.error("获取系统信息失败", e);
            return R.error("获取系统信息失败: " + e.getMessage());
        }
    }

    /**
     * 获取操作系统实时信息
     */
    @GetMapping("/operateSystemRealtime")
    @Operation(summary = "操作系统实时信息", description = "获取操作系统实时信息")
    public R<OperateSystemRealtimeResp> operateSystemRealtime() {
        try {
            return R.success(systemMonitorLogic.operateSystemRealtime());
        } catch (Exception e) {
            log.error("获取系统信息失败", e);
            return R.error("获取系统信息失败: " + e.getMessage());
        }
    }

    /**
     * 获取JVM基本信息
     */
    @GetMapping("/jvmBasic")
    @Operation(summary = "JVM信息", description = "获取JVM基本信息")
    public R<JvmBasicResp> jvmBasic() {
        try {
            return R.success(systemMonitorLogic.jvmBasic());
        } catch (Exception e) {
            log.error("获取JVM信息失败", e);
            return R.error("获取JVM信息失败: " + e.getMessage());
        }
    }

    /**
     * 获取JVM启动参数
     */
    @GetMapping("/arguments")
    @Operation(summary = "获取JVM启动参数", description = "获取JVM启动时的所有参数，包括内存、GC等配置")
    public R<JvmArgumentsResp> getJvmArguments() {
        try {
            JvmArgumentsResp arguments = systemMonitorLogic.getJvmArguments();
            return R.success(arguments);
        } catch (Exception e) {
            log.error("获取JVM启动参数失败", e);
            return R.error("获取失败: " + e.getMessage());
        }
    }

    /**
     * 获取JVM实时信息
     */
    @GetMapping("/jvmRealtime")
    @Operation(summary = "JVM实时信息", description = "获取JVM实时信息")
    public R<JvmRealtimeResp> jvmRealtime() {
        try {
            return R.success(systemMonitorLogic.jvmRealtime());
        } catch (Exception e) {
            log.error("获取JVM信息失败", e);
            return R.error("获取JVM信息失败: " + e.getMessage());
        }
    }


    /**
     * 获取堆内存区域信息（按区分组）
     */
    @GetMapping("/heapPools")
    @Operation(summary = "获取堆内存区域信息", description = "按新生代、老年代等区域分组显示堆内存使用情况")
    public R<Map<String, List<MemoryPoolDetailResp>>> getHeapMemoryPools() {
        try {
            Map<String, List<MemoryPoolDetailResp>> pools = systemMonitorLogic.getHeapMemoryPools();
            return R.success(pools);
        } catch (Exception e) {
            log.error("获取堆内存区域信息失败", e);
            return R.error("获取失败: " + e.getMessage());
        }
    }

    /**
     * 获取所有内存池信息
     */
    @GetMapping("/memoryPools")
    @Operation(summary = "获取所有内存池信息", description = "获取包括堆和非堆的所有内存池详细信息")
    public R<List<MemoryPoolDetailResp>> getAllMemoryPools() {
        try {
            List<MemoryPoolDetailResp> pools = systemMonitorLogic.getAllMemoryPools();
            return R.success(pools);
        } catch (Exception e) {
            log.error("获取内存池信息失败", e);
            return R.error("获取失败: " + e.getMessage());
        }
    }

    /**
     * 获取类加载详细信息
     */
    @GetMapping("/classLoading")
    @Operation(summary = "获取类加载信息", description = "获取已加载、总加载、已卸载的类统计信息")
    public R<ClassLoadingDetailResp> getClassLoadingDetail() {
        try {
            ClassLoadingDetailResp info = systemMonitorLogic.getClassLoadingDetail();
            return R.success(info);
        } catch (Exception e) {
            log.error("获取类加载信息失败", e);
            return R.error("获取失败: " + e.getMessage());
        }
    }

    /**
     * 获取磁盘使用情况
     */
    @GetMapping("/disk")
    @Operation(summary = "获取磁盘信息", description = "获取所有磁盘分区的使用情况")
    public R<DiskInfoResp> getDiskInfo() {
        try {
            DiskInfoResp diskInfo = systemMonitorLogic.getDiskInfo();
            return R.success(diskInfo);
        } catch (Exception e) {
            log.error("获取磁盘信息失败", e);
            return R.error("获取磁盘信息失败: " + e.getMessage());
        }
    }


    /**
     * 获取数据库连接池信息
     */
    @GetMapping("/database")
    @Operation(summary = "获取数据库连接池信息", description = "获取数据库连接池的连接数、使用率等信息")
    public R<DatabaseInfoRealtimeResp> getDatabaseInfo() {
        try {
            return R.success(systemMonitorLogic.databaseInfoRealtime());
        } catch (Exception e) {
            log.error("获取数据库连接池信息失败", e);
            return R.error("获取数据库信息失败: " + e.getMessage());
        }
    }

    /**
     * 获取GC信息
     */
    @GetMapping("/getGcInfo")
    @Operation(summary = "获取GC信息", description = "获取垃圾回收器的统计信息")
    public R<GcInfoResp> getGcInfo() {
        try {
            return R.success(systemMonitorLogic.getGcInfo());
        } catch (Exception e) {
            log.error("获取GC信息失败", e);
            return R.error("获取GC信息失败: " + e.getMessage());
        }
    }

    /**
     * 获取线程信息
     */
    @GetMapping("/threads")
    @Operation(summary = "获取线程信息", description = "获取JVM线程统计信息")
    public R<ThreadInfoResp> getThreadInfo() {
        try {
            return R.success(systemMonitorLogic.getThreadInfo());
        } catch (Exception e) {
            log.error("获取线程信息失败", e);
            return R.error("获取线程信息失败: " + e.getMessage());
        }
    }

    /**
     * 手动触发GC操作
     */
    @GetMapping("/doGc")
    @Operation(summary = "强制垃圾回收", description = "手动触发JVM垃圾回收，返回GC执行结果")
    public R<GcResultResp> doGc() {
        try {
            GcResultResp gcResult = systemMonitorLogic.forceGc();

            // 记录操作日志
            if (Boolean.TRUE.equals(gcResult.getSuccess())) {
                log.info("手动触发GC成功，耗时: {}ms，释放内存: {}MB",
                        gcResult.getDuration(), gcResult.getMemoryReleasedMB());
            }

            return R.success(gcResult);
        } catch (Exception e) {
            log.error("强制GC失败", e);
            return R.error("执行GC失败: " + e.getMessage());
        }
    }

}